﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

using Wicresoft.Shell.Core;

namespace Wicresoft.Shell.Package.AppExp
{
    public class UmcDesignSurface : DesignSurface
    {
        //when update design view , we dont want trigger IComponentChangeService , so we add this flag
        private bool flag;
        public UmcDesignSurface(IServiceProvider parentProvider)
            : base(parentProvider)
        {

            InitializeDesigner();

            // Host control is selected by default
            UpdateProperty();

            //IMenuCommandService ims = this.GetService(typeof(IMenuCommandService)) as IMenuCommandService;
            //Debug.Assert(ims != null);


            ISelectionService ss = (ISelectionService)base.GetService(typeof(ISelectionService));
            Debug.Assert(ss != null);
            // Update property when we select different control
            ss.SelectionChanged += new EventHandler(delegate(object sender, EventArgs e)
            {
                UpdateProperty();
            });

            
            IComponentChangeService ccs = (IComponentChangeService)base.GetService(typeof(IComponentChangeService));
            Debug.Assert(ccs != null);
            
            ccs.ComponentChanged += new ComponentChangedEventHandler(delegate(object sender, ComponentChangedEventArgs e)
            {
                Logger.Output("ccs.ComponentChanged");
                // Update property when we change the control
                UpdateProperty();
                UpdateCodeInternal();
            });
            ccs.ComponentAdded += new ComponentEventHandler(ccs_ComponentAdded);
            ccs.ComponentRemoved += new ComponentEventHandler(ccs_ComponentRemoved);

            flag = true;
        }

        public delegate void UpdateCode(string code);
        public event UpdateCode OnUpdateCode;

        private void InitializeDesigner()
        {
            designerLoader = new UmcDesignerLoader();
            base.ServiceContainer.AddService(typeof(INameCreationService), designerLoader);
            //this.ServiceContainer.AddService(typeof(IMenuCommandService), new MenuCommandService(this));
            base.BeginLoad(designerLoader);
        }

        private void UpdateProperty()
        {
            ISelectionService ss = (ISelectionService)base.GetService(typeof(ISelectionService));
            Debug.Assert(ss != null);

            SelectionContainer mySelectionContainer = new SelectionContainer();
            mySelectionContainer.SelectedObjects = ss.GetSelectedComponents().Cast<Object>().ToArray();

            ITrackSelection track = GetService(typeof(STrackSelection)) as ITrackSelection;
            if (track != null)
            {
                track.OnSelectChange(mySelectionContainer);
            }
        }

        private void UpdateCodeInternal()
        {
            if (flag)
            {
                if (OnUpdateCode != null)
                {
                    OnUpdateCode(this.GetCode());
                }
            }
        }

        void ccs_ComponentRemoved(object sender, ComponentEventArgs e)
        {
            UpdateCodeInternal();
        }

        void ccs_ComponentAdded(object sender, ComponentEventArgs e)
        {
            UpdateCodeInternal();
        }

        private string GetCode()
        {
            return designerLoader.GetCode();
        }

        internal void UpdateDesignerView(string code)
        {
            //before update design view , set flag = false to prevent updating code
            flag = false;
            if (designerLoader.UpdateDesignerView(code))
            {
                //after update design view , set flag = true
                flag = true;
            }
            else
            {
                Logger.Output(string.Format(
                    "Error(Inner):designerLoader.UpdateDesignerView return false, the designer will be unavailable unless you fix the problem of the code behind!")
                    , WriteTo.OutputWindow);
            }

        }

        protected override void Dispose(bool disposing)
        {
            if (designerLoader != null)
            {
                designerLoader.Dispose();
                designerLoader = null;
            }
            base.Dispose(disposing);
        }

        private UmcDesignerLoader designerLoader;
    }
}
